home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CU Amiga Super CD-ROM 27
/
CU Amiga Magazine's Super CD-ROM 27 (1998)(EMAP Images)(GB)[!][issue 1998-10].iso
/
CUCD
/
Sound
/
SPlayer
/
Socks5
/
src
/
lib
/
rld.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-07-20
|
14KB
|
293 lines
/* Copyright (c) 1995,1996,1997 NEC Corporation. All rights reserved. */
/* */
/* The redistribution, use and modification in source or binary forms of */
/* this software is subject to the conditions set forth in the copyright */
/* document ("Copyright") included with this distribution. */
/*
* $Id: rld.c,v 1.33.4.2 1998/06/29 22:42:35 salman Exp $
*/
/* This file has all the stubs to get the "real" functions out of libc, */
/* libnsl or libsocket. Sometimes we need the "real" function, because */
/* we've replaced it (i.e. connect), sometimes we need it because we will */
/* have mangled some static data that it keeps around (i.e. getenv). */
#include "socks5p.h"
#include "addr.h"
#include "log.h"
#ifdef HAVE_DLOPEN
#include <dlfcn.h>
#ifndef RTLD_LAZY
#define RTLD_LAZY 1
#endif
#ifndef RTLD_GLOBAL
#define RTLD_GLOBAL 0
#endif
#ifndef LIBC_NAME
#define LIBC_NAME NULL
#endif
#ifndef LIBNSL_NAME
#define LIBNSL_NAME NULL
#endif
#ifndef LIBRESOLV_NAME
#define LIBRESOLV_NAME NULL
#endif
#ifndef LIBSOCKET_NAME
#define LIBSOCKET_NAME NULL
#endif
#ifndef LIBDGC_NAME
#define LIBDGC_NAME NULL
#endif
/* Lets hope we don't have to do this for too many OS's...Maybe configure */
/* should figure it out...? */
#define TRY_LIBC (1 << 0)
#define TRY_LIBNSL (1 << 1)
#define TRY_LIBSOCKET (1 << 2)
#define TRY_LIBRESOLV (1 << 3)
#define NO_RTLD_NEXT (1 << 4)
#define USE_RTLD_GLOBAL (1 << 5)
#ifdef FOR_SHARED_LIBRARY
#define GETSYM(handle, libname, flags) \
if (!(handle) && ((handle) = dlopen((libname), (flags))) == NULL) { \
return; \
} else if ((*fptr = dlsym((handle), name)) != NULL) { \
return; \
} else
#define DGETSYM(handle, libname, flags) \
if (!(handle) && ((handle) = dlopen((libname), (flags))) == NULL) { \
S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Unable to open shared library: %s", (libname)); \
} else if ((*fptr = dlsym((handle), name)) != NULL) { \
S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "Found %s in %s%s", name, (libname), libmask&USE_RTLD_GLOBAL?"(g)":""); \
return; \
} else
#define GETSYMHANDLE(mask, handle, libname, envname, flags) \
if (libmask & (mask)) { \
static void *(handle) = NULL; \
char *lname = (envname)?getenv((envname)):NULL; \
if (lname == NULL) lname = (libname); \
if (lname) GETSYM((handle), lname, (flags)); \
} else
#define DGETSYMHANDLE(mask, handle, libname, envname, flags) \
if (libmask & (mask)) { \
static void *(handle) = NULL; \
char *lname = (envname)?getenv((envname)):NULL; \
if (lname == NULL) lname = (libname); \
if (lname) DGETSYM((handle), lname, (flags)); \
} else
#define GETFUNC(name, flags, invalid, cast, args, rtype) \
static void *func = NULL; \
static rtype rval; \
GetOriginalFunc(&func, (name), (flags)); \
if (!func || func == (void *)-1) return (invalid); \
lsInRLDFunctions = 1; \
rval = (cast func)args; \
lsInRLDFunctions = 0; \
return rval
#define DGETFUNC(name, flags, invalid, cast, args, rtype) \
static void *func = NULL; \
static rtype rval; \
DGetOriginalFunc(&func, (name), (flags)); \
if (!func || func == (void *)-1) return (invalid); \
S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "RLD: Found %s at %p", (name)+1, func); \
lsInRLDFunctions = 1; \
rval = (cast func)args; \
lsInRLDFunctions = 0; \
S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "RLD: %s returned: %x", (name)+1, (rval)); \
return rval
extern int lsInRLDFunctions;
/* Look up name in libc.so, libnsl.so, and libsocket.so, if its there return */
/* the symbol we found, otherwise return NULL... */
static void GetOriginalFunc(void **fptr, char *name, int libmask) {
/* Synchronize access to func and lib opening functions if we can... */
#ifndef __FreeBSD__
name++;
#endif
if (*fptr) return;
/* Still have to figure out what OSs USE_RTLD_NEXT is valid for. For */
/* most that I've tried, it hasn't worked right... */
#if defined(RTLD_NEXT) && defined(USE_RTLD_NEXT)
if (name && ~libmask & NO_RTLD_NEXT && (*fptr = dlsym(RTLD_NEXT, name)) != NULL) {
return;
}
#endif
GETSYMHANDLE(TRY_LIBRESOLV, libresolv_handle, LIBRESOLV_NAME, "LIBRESOLV_NAME", RTLD_LAZY);
GETSYMHANDLE(TRY_LIBNSL, libnsl_handle, LIBNSL_NAME, "LIBNSL_NAME", RTLD_LAZY);
GETSYMHANDLE(TRY_LIBSOCKET, libsocket_handle, LIBSOCKET_NAME, "LIBSOCKET_NAME", RTLD_LAZY);
GETSYMHANDLE(TRY_LIBSOCKET, libdgc_handle, LIBDGC_NAME, "LIBDGC_NAME", RTLD_LAZY);
GETSYMHANDLE(TRY_LIBC, libc_handle, LIBC_NAME, "LIBC_NAME", RTLD_LAZY);
}
/* Look up name in libc.so, libnsl.so, and libsocket.so, if its there return */
/* the symbol we found, otherwise return NULL... */
static void DGetOriginalFunc(void **fptr, char *name, int libmask) {
/* Synchronize access to func and lib opening functions if we can... */
#ifndef __FreeBSD__
name++;
#endif
if (*fptr) return;
S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "RLD: %s", name);
/* Still have to figure out what OSs USE_RTLD_NEXT is valid for. For */
/* most that I've tried, it hasn't worked right... */
#if defined(RTLD_NEXT) && defined(USE_RTLD_NEXT)
if (name && ~libmask & NO_RTLD_NEXT && (*fptr = dlsym(RTLD_NEXT, name)) != NULL) {
S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "RLD: Used RTLD_NEXT");
return;
}
#endif
DGETSYMHANDLE(TRY_LIBRESOLV, libresolv_handle, LIBRESOLV_NAME, "LIBRESOLV_NAME", RTLD_LAZY);
DGETSYMHANDLE(TRY_LIBNSL, libnsl_handle, LIBNSL_NAME, "LIBNSL_NAME", RTLD_LAZY);
DGETSYMHANDLE(TRY_LIBSOCKET, libsocket_handle, LIBSOCKET_NAME, "LIBSOCKET_NAME", RTLD_LAZY);
DGETSYMHANDLE(TRY_LIBSOCKET, libdgc_handle, LIBDGC_NAME, "LIBDGC_NAME", RTLD_LAZY);
DGETSYMHANDLE(TRY_LIBC, libc_handle, LIBC_NAME, "LIBC_NAME", RTLD_LAZY);
S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(0), 0, "RLD: Unable to find symbol %s in suggested places: %d", name, libmask);
}
struct hostent *REAL(gethostbyname)(const char *name) {
struct hostent *hp;
static void *func = NULL;
S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "RLD: gethostbyname: %s", name);
GetOriginalFunc(&func, "_gethostbyname", TRY_LIBC | TRY_LIBNSL | TRY_LIBRESOLV);
if (!func || func == (void *)-1) return NULL;
lsInRLDFunctions = 1;
hp = ((struct hostent *(*)P((const char *)))func)(name);
lsInRLDFunctions = 0;
S5LogUpdate(S5LogDefaultHandle, S5_LOG_DEBUG(10), 0, "RLD: gethostbyname results: %s %s", name, hp?hp->h_name:"???");
return hp;
}
int REAL(getpeername) (S5IOHandle sd, ss *sa, int *slen) {
GETFUNC("_getpeername", TRY_LIBC | TRY_LIBSOCKET, -1, (int (*)P((S5IOHandle, ss *, int *))), (sd, sa, slen), int);
}
int REAL(getsockname) (S5IOHandle sd, ss *sa, int *slen) {
GETFUNC("_getsockname", TRY_LIBC | TRY_LIBSOCKET, -1, (int (*)P((S5IOHandle, ss *, int *))), (sd, sa, slen), int);
}
int REAL(accept) (S5IOHandle sd, ss *sa, int *slen) {
GETFUNC("_accept", TRY_LIBC | TRY_LIBSOCKET, -1, (int (*)P((S5IOHandle, ss *, int *))), (sd, sa, slen), int);
}
int REAL(connect) (S5IOHandle sd, const ss *sa, int slen) {
GETFUNC("_connect", TRY_LIBC | TRY_LIBSOCKET, -1, (int (*)P((S5IOHandle, const ss *, int))), (sd, sa, slen), int);
}
int REAL(bind) (S5IOHandle sd, const ss *sa, int slen) {
GETFUNC("_bind", TRY_LIBC | TRY_LIBSOCKET, -1, (int (*)P((S5IOHandle, const ss *, int))), (sd, sa, slen), int);
}
int REAL(recvfrom) (S5IOHandle sd, IOPTRTYPE buf, IOLENTYPE blen, int f, ss *sa, int *slen) {
GETFUNC("_recvfrom", TRY_LIBC | TRY_LIBSOCKET, -1, (int (*)P((S5IOHandle, char *, int, int, ss *, int *))), (sd, buf, blen, f, sa, slen), int);
}
int REAL(sendto) (S5IOHandle sd, const IOPTRTYPE buf, IOLENTYPE blen, int f, const ss *sa, int slen) {
GETFUNC("_sendto", TRY_LIBC | TRY_LIBSOCKET, -1, (int (*)P((S5IOHandle, const char *, int, int, const ss *, int))), (sd, buf, blen, f, sa, slen), int);
}
int REAL(recvmsg) (S5IOHandle sd, const ms *sa, int slen) {
GETFUNC("_recvmsg", TRY_LIBC | TRY_LIBSOCKET, -1, (int (*)P((S5IOHandle, const ms *, int ))), (sd, sa, slen), int);
}
int REAL(sendmsg) (S5IOHandle sd, const ms *sa, int slen) {
GETFUNC("_sendmsg", TRY_LIBC | TRY_LIBSOCKET, -1, (int (*)P((S5IOHandle, const ms *, int))), (sd, sa, slen), int);
}
int REAL(recv) (S5IOHandle sd, IOPTRTYPE buf, IOLENTYPE blen, int f) {
GETFUNC("_recv", TRY_LIBC | TRY_LIBSOCKET, -1, (int (*)P((S5IOHandle, char *, int, int))), (sd, buf, blen, f), int);
}
int REAL(send) (S5IOHandle sd, const IOPTRTYPE buf, IOLENTYPE blen, int f) {
GETFUNC("_send", TRY_LIBC | TRY_LIBSOCKET, -1, (int (*)P((S5IOHandle, const char *, int, int))), (sd, buf, blen, f), int);
}
int REAL(shutdown) (S5IOHandle sd, int how) {
GETFUNC("_shutdown", TRY_LIBC | TRY_LIBSOCKET, -1, (int (*)P((S5IOHandle, int))), (sd, how), int);
}
int REAL(listen) (S5IOHandle sd, int n) {
GETFUNC("_listen", TRY_LIBC | TRY_LIBSOCKET, -1, (int (*)P((S5IOHandle, int))), (sd, n), int);
}
S5IOHandle REAL(dup) (S5IOHandle sd) {
GETFUNC("_dup", TRY_LIBC, S5InvalidIOHandle, (S5IOHandle (*)P((S5IOHandle))), (sd), S5IOHandle);
}
S5IOHandle REAL(dup2) (S5IOHandle sd, S5IOHandle s2) {
GETFUNC("_dup2", TRY_LIBC, S5InvalidIOHandle, (S5IOHandle (*)P((S5IOHandle, S5IOHandle))), (sd, s2), S5IOHandle);
}
int REAL(close) (S5IOHandle sd) {
GETFUNC("_close", TRY_LIBC, -1, (int (*)P((S5IOHandle))), (sd), int);
}
int REAL(fclose) (FILE *fp) {
GETFUNC("_fclose", TRY_LIBC, -1, (int (*)P((FILE *))), (fp), int);
}
IORETTYPE REAL(read) (S5IOHandle sd, IOPTRTYPE buf, IOLENTYPE blen) {
GETFUNC("_read", TRY_LIBC, -1, (IORETTYPE (*)P((S5IOHandle, IOPTRTYPE, IOLENTYPE))), (sd, buf, blen), IORETTYPE);
}
IORETTYPE REAL(write) (S5IOHandle sd, const IOPTRTYPE buf, IOLENTYPE blen) {
GETFUNC("_write", TRY_LIBC, -1, (IORETTYPE (*)P((S5IOHandle, const IOPTRTYPE, IOLENTYPE))), (sd, buf, blen), IORETTYPE);
}
struct tm *REAL(localtime)(const time_t *clock) {
static void *func = NULL;
static struct tm * rval;
GetOriginalFunc(&func, "_localtime", TRY_LIBC);
if (!func || func == (void *)-1) return (NULL);
lsInRLDFunctions = 1;
rval = ((struct tm * (*)(const time_t *))func)(clock);
lsInRLDFunctions = 0;
return rval;
}
void REAL(longjmp) (jmp_buf env, int val) {
static void *func = NULL;
GetOriginalFunc(&func, "_longjmp", TRY_LIBC);
if (!func || func == (void *)-1) return;
lsInRLDFunctions = 0;
((void (*)(jmp_buf, int))func)(env, val);
}
int REAL(select) (S5IOHandle wd, fd_set *rs, fd_set *ws, fd_set *es, struct timeval *to) {
GETFUNC("_select", TRY_LIBC, -1, (int (*)P((S5IOHandle, fd_set *, fd_set *, fd_set *, struct timeval *))), (wd, rs, ws, es, to), int);
}
#ifdef HAVE_RRESVPORT
S5IOHandle REAL(rresvport) (int *port) {
GETFUNC("_rresvport", TRY_LIBC | TRY_LIBSOCKET, S5InvalidIOHandle, (S5IOHandle (*)P((int *))), (port), S5IOHandle);
}
#endif
#endif /* FOR_SHARED_LIBRARY */
#endif /* HAVE_DLOPEN */